<?php


namespace App\Services\Accompany;


use App\Enums\AccompanyEnum;
use App\Exceptions\BasicException;
use App\Jobs\QiPao\AccompanyCancelJob;
use App\Jobs\QiPao\AccompanyFinishJob;
use App\Models\MainDB\Accompany\AccompanyAbility;
use App\Models\MainDB\Accompany\AccompanyCouponUser;
use App\Models\MainDB\Accompany\AccompanyLabel;
use App\Models\MainDB\Accompany\AccompanyOrderRefund;
use App\Models\MainDB\Accompany\AccompanyUser;
use App\Models\MainDB\Chat;
use App\Models\MainDB\Config;
use App\Models\MainDB\Region;
use App\Models\MainDB\UserData;
use App\Repositories\Accompany\AccompanyAbilityRepository;
use App\Repositories\Accompany\AccompanyOrderLogRepository;
use App\Repositories\Accompany\AccompanyOrderRepository;
use App\Models\MainDB\Accompany\AccompanyOrder;
use App\Repositories\WalletRepository;
use App\Response\Response;
use App\Services\Tools\PushChatService;
use App\Services\Tools\PushService;
use App\Services\Tools\RedisService;
use App\Services\Tools\RongCloudService;
use Exception;
use Illuminate\Support\Facades\DB;
use App\Services\Tools\JwtService;

class AccompanyOrderService
{
    /**
     * 接单截止时间
     */
    const endTime = 3 * 60;//3分钟

    /**
     * 订单完成时间
     */
    const FINISH_TIME = 24 * 3600; //24小时

    /**
     * 我的下单列表
     * @param $userId
     * @param $page
     * @param $perPage
     * @return array
     */
    public function getOrderList($userId, $page, $perPage)
    {
        $where = [
            ['user_id', '=', $userId],
        ];
        $statusArr = [-3, -2, -1, 2, 3];
        $repoOrder = AccompanyOrderRepository::getInstance();
        $orders = $repoOrder->page($where, $page, $statusArr, $perPage);
        $data = [];
        foreach ($orders->items() as $order) {
            // $data[] = $this->buildOrderData($order, $order['anchor'], $order['accompany_ability'], $order['accompany_ability']['accompany_game']);
            $data[] = $this->buildOrderData($order, $order['anchor'], $order['accompany_ability'], $order['accompany_ability']['accompany_game'], 0);
        }
        return [
            'service_list' => $this->getUserOngoingOrder($userId),
            'list'         => $data,
            'total'        => $orders->total(),
            "meta"         => [
                "total" => $orders->total(),
                "page"  => $orders->currentPage(),
                "limit" => $orders->perPage(),
            ],
        ];
    }

    /**
     * 我的接单列表
     * @param $userId
     * @param $page
     * @param $perPage
     * @return array
     */
    public function getAnchorOrderList($userId, $page, $perPage)
    {
        $where = [
            ['anchor_id', '=', $userId],
            // ['status', '<>', -1],
        ];
        $statusArr = [-2, -1, 2, 3];
        $repoOrder = AccompanyOrderRepository::getInstance();
        $orders = $repoOrder->page($where, $page, $statusArr, $perPage);
        $data = [];
        foreach ($orders->items() as $order) {
            // $data[] = $this->buildOrderData($order, $order['user_data'], $order['accompany_ability'], $order['accompany_ability']['accompany_game']);
            $data[] = $this->buildOrderData($order, $order['user_data'], $order['accompany_ability'], $order['accompany_ability']['accompany_game']);
        }
        return [
            'service_list' => $this->getAnchorOngoingOrder($userId),
            'list'         => $data,
            'total'        => $orders->total(),
            "meta"         => [
                "total" => $orders->total(),
                "page"  => $orders->currentPage(),
                "limit" => $orders->perPage(),
            ],
        ];
    }


    /**
     * 我的接单列表
     * @param $userId
     * @param int $limit
     * @param bool $flush
     * @return array
     */
    public function getOrderMessageList($userId, int $limit = 0, $flush = true): array
    {
        $orWhere = [];
        $orWhere['user_id'] = $userId;
        $orWhere['anchor_id'] = $userId;
        $orders = AccompanyOrder::query()
            ->with(['user_data', 'anchor', 'accompany_ability', 'accompany_ability.accompany_game', 'refund'])
            ->where(function ($query) use ($orWhere) {
                $query->orWhere($orWhere);
            })
            ->where(function ($query){
                $query->whereIn('status', [-1, 0, 1])->orWhere(function($query){
                    $query->where('refund_id','>',0)->whereIn('refund_status',[0,-1,-3,2]);
                });
            })
            ->orderBy('created_at', 'desc');
        if($limit){
            $orders->limit($limit);
        }
        $orders = $orders->get();
        $data = [];
        if($flush){
            $this->setUserNewsStatus($userId);
        }
        foreach ($orders as $key => $order) {
            $userData = $order['user_data'];
            $anchor = $order['anchor'];
            $endTime = time() - strtotime($order->created_at);
            $endTime = self::endTime - $endTime;
            $endTime = $endTime < 0 ? 0 : $endTime;
            $isAccompanyOrder = ($userId == $order->anchor_id) ? 1 : 2; //  1 我的接单 2 我的下单,
            $isAnchor = $isAccompanyOrder == 1 ? 1 : 0;
            $closed_at = date('Y-m-d H:i:s', strtotime($order->created_at) + self::endTime);
            $content = '';
            // if ($order->status == -1) {
            //     $content = '大神未通过您的订单，下单前先和大神沟通一下吧';
            // } elseif ($order->status == 1) {
            //     $content = '大神通过您的订单，快去让大神带飞吧';
            // } elseif ($isAccompanyOrder == 1 && in_array($order->status, [2, 3])) {
            //     $content = $userData['nickname'] . '给您下了订单';
            // }
            $designation = AccompanyEnum::ACCOMPANY_NAME[$order->type] ?? '';
            if ($order->status == -1) {
                $content = $isAccompanyOrder == 1 ? $userData['nickname'] . '给您下了订单' : "{$designation}未通过您的订单，下单前先和{$designation}沟通一下吧";
            }elseif ($order->refund_id > 0) {
                if(in_array($order->refund->status,[0,1])){
                    $content = $isAccompanyOrder == 1 ? '收到退款消息，请前往查看' : '待退款';
                }elseif($order->refund->status == 2){
                    $content = $isAccompanyOrder == 1 ? '等待平台审核' : "{$designation}拒绝退款，请耐心等待平台审核退款";
                }elseif($order->refund->status == 3){
                    $content = '订单退款成功，【'.$order->refund->audit_reason.'】';
                }elseif($order->refund->status == 4){
                    $content = '订单退款失败，【'.$order->refund->audit_reason.'】';
                }
            } elseif ($order->status == 1) {
                $content = $isAccompanyOrder == 1 ? $userData['nickname'] . '给您下了订单' : "{$designation}通过您的订单，快去让{$designation}带飞吧";
            }elseif ($order->status == 0) {
                if($isAccompanyOrder == 2){  //用户不显示这条消息
                    unset($orders[$key]);
                    continue;
                }
                $content = $isAccompanyOrder == 1 ? $userData['nickname'] . '给您下了订单' : '';
            }
            $data[] = [
                'id'                 => $order->id,
                'order_no'           => $order->order_no,
                'user_id'            => $order->user_id,
                'anchor_id'          => $order->anchor_id,
                'game_id'            => $order->game_id,
                'game_name'          => $order->game_name,
                'content'            => $content,
                'game_picture'       => $order['accompany_ability']['accompany_game']['picture'] ?? '',
                'service_time'       => $this->time($order->service_time),
                'count'              => $order->count,
                'price'              => $order->price,
                'coupon_price'       => $order->coupon_price,
                'total_price'        => $order->total_price,
                'remark'             => $order->remark,
                'status'             => $order->status,
                'refund_status'      => $order->refund_status,
                'took_at'            => $order->took_at,
                'unit'               => $order->unit,
                'created_at'         => $order->created_at->toDateTimeString(),
                'is_accompany_order' => $isAccompanyOrder,
                'end_time'           => $endTime,
                'closed_at'          => $closed_at,
                'action_status'      => $this->getActionStatus($order->status, $order->grade),
                'status_name'        => $this->getStatusName($order,$isAnchor, true),
                'user_data'          => [
                    'user_id'      => $userData['user_id'],
                    'sex'          => $userData['sex'],
                    'head_picture' => $userData['head_picture'],
                    'nickname'     => $userData['nickname'],
                    'mood'         => $userData['mood'],
                    'is_accompany' => $userData['is_accompany'],
                ],
                'anchor'             => [
                    'user_id'      => $anchor['user_id'],
                    'sex'          => $anchor['sex'],
                    'head_picture' => $anchor['head_picture'],
                    'nickname'     => $anchor['nickname'],
                    'mood'         => $anchor['mood'],
                    'is_accompany' => $anchor['is_accompany'],
                ],
            ];
        }
        return $data;
    }

    /**
     * 我的接单列表已读未读
     * @param $userId
     * @return array
     */
    public function getOrderMessage($userId)
    {
        $count = AccompanyOrder::query()
            //->with(['user_data', 'anchor', 'accompany_ability', 'accompany_ability.accompany_game'])
            ->where(function ($query) use ($userId) {
                $query->where(['user_id' => $userId , 'user_news' => 0])->orWhere(function($query) use($userId){
                    $query->where(['anchor_id' => $userId , 'anchor_news' => 0]);
                });
            })
            ->where(function ($query){
                $query->whereIn('status', [-1, 0, 1])->orWhere(function($query){
                    $query->where('refund_id','>',0)->whereIn('refund_status',[0,-1,-3,2]);
                });
            })
            ->count();
        $data = [];
        $list = $this->getOrderMessageList($userId, 1, false);
        if(!empty($list)){
            $data = [
                'content' => $list[0]['content'],
                'source' => 4,
                'add_time' => $this->getTime($list[0]['created_at']),
            ];
        }
        return ['data' => $data, 'count' => $count];
    }

    /**
     * 订单消息已读
     * @param $userId
     */
    public function setUserNewsStatus($userId)
    {
        AccompanyOrder::query()->where('user_id', $userId)->where('user_news',0)->update(['user_news' => 1]);
        AccompanyOrder::query()->where('anchor_id', $userId)->where('anchor_news',0)->update(['anchor_news' => 1]);
        return true;
    }


    /**
     * 达人中心
     * @param $userId
     * @return array
     */
    public function userInfo($userId)
    {
        $todayStartTime = date('Y-m-d' . ' 00:00:00');
        $todayEndTime = date('Y-m-d' . ' 23:59:59');
        $repoOrder = AccompanyOrderRepository::getInstance();
        [$weekStartTime, $weekEndTime] = getStartAndEndTimeOfTheWeek(date('Y-m-d'));
        $todayOrderCount = $repoOrder->getOrderCount($userId, $todayStartTime, $todayEndTime);
        $weekOrderCount = $repoOrder->getOrderCount($userId, $weekStartTime, $weekEndTime);
        $profit = $repoOrder->getTotalProfit($userId, $weekStartTime, $weekEndTime);
        $freezeFee = $repoOrder->getTotalFreezeFee($userId);

        $level  = AccompanyUser::query()
            ->select(['name'])
            ->leftJoin('ln_accompany_level as al','al.id','=','ln_accompany_user.level_id')
            ->where('user_id',$userId)
            ->first();
        return [
            'day_count'  => $todayOrderCount, // 今日接单数量
            'week_count' => $weekOrderCount,  // 本周接单数量
            'week_price' => $profit,          // 本周收益
            'un_settle'  => $freezeFee,       // 冻结收益
            'level_name' => $level['name'] ?? '青铜',
        ];


    }

    /**
     * @param $abilityId
     * @param $count
     * @param $userId
     * 确认订单
     * @return array
     */
    public function confirmOrder($abilityId, $count, $userId)
    {
        $ability = AccompanyAbility::query()->where('ln_accompany_ability.id', $abilityId)
            ->select(['ln_accompany_ability.id', 'ln_accompany_ability.user_id', 'game_name', 'game_level', 'game_service',
                'grade', 'order_count', 'ln_accompany_ability.price', 'ln_accompany_ability.unit', 'ag.picture as game_picture',
                'ln_accompany_ability.unit_quantity','ln_accompany_ability.unit_desc','ln_accompany_ability.type'])
            ->leftJoin('ln_accompany_game as ag', 'ln_accompany_ability.game_id', '=', 'ag.id')
            ->where('ln_accompany_ability.status', 1)
            ->first();
        if (empty($ability)) {
            throw new BasicException(-1, '技能不存在');
        }
        $abilityList = AccompanyAbilityRepository::getInstance()->info($ability['user_id'], ['ln_accompany_ability.id', 'ln_accompany_ability.user_id', 'game_name', 'game_level', 'game_service',
            'grade', 'order_count', 'ln_accompany_ability.price', 'ln_accompany_ability.unit', 'ag.picture as game_picture']);
        $price = $ability['price'] * $count;

        $coupon = new AccompanyCouponService();
        $couponInfo = $coupon->couponPrice($price, $userId);
        //冥想不使用优惠卷
        if ($ability['type'] == AccompanyEnum::ACCOMPANY_TYPE_MEDITATION) {
            $couponInfo['reduced_price'] = 0;

        }
        $price = $price - $couponInfo['reduced_price'];
        $user = UserData::query()->select(['user_id', 'sex', 'nickname', 'head_picture'])->where('user_id', $ability['user_id'])->first();


        $coin = WalletRepository::getInstance()->userCoin($userId);
        $reducedPrice = '';
        if ($couponInfo['reduced_price'] > 0) {
            $reducedPrice = '减' . $couponInfo['reduced_price'] . 'M豆';
        }


        return [
            'ability'       => $ability,
            'abilityList'   => $abilityList,
            'user'          => $user,
            'count'         => $count,
            'reduced_price' => $reducedPrice,
            'coupon_id'     => $couponInfo['id'],
            'price'         => $price,
            'coin'          => $coin,
        ];


    }

    /**
     * 获取我的数据统计数据
     * @param $userId
     * @return
     */
    public function getStatisticsByUserId($userId)
    {
        $todayStartTime = date('Y-m-d' . ' 00:00:00');
        $todayEndTime = date('Y-m-d' . ' 23:59:59');
        $repoOrder = AccompanyOrderRepository::getInstance();
        [$weekStartTime, $weekEndTime] = getStartAndEndTimeOfTheWeek(date('Y-m-d'));
        $todayOrderCount = $repoOrder->getOrderCount($userId, $todayStartTime, $todayEndTime);
        $weekOrderCount = $repoOrder->getOrderCount($userId, $weekStartTime, $weekEndTime);
        $profit = $repoOrder->getTotalProfit($userId, $weekStartTime, $weekEndTime);
        $freezeFee = $repoOrder->getTotalFreezeFee($userId);

        $level  = AccompanyUser::query()
            ->select(['name'])
            ->leftJoin('ln_accompany_level as al','al.id','=','ln_accompany_user.level_id')
            ->where('user_id',$userId)
            ->first();
        return [
            'today_order_count' => $todayOrderCount, // 今日接单数量
            'week_order_count'  => $weekOrderCount, // 本周接单数量
            'profit'            => $profit, // 本周收益
            'freeze_fee'        => $freezeFee, // 冻结收益
            'level_name' => $level['level_name'] ?? '青铜',
        ];
    }


    /**
     * @param $order
     * @param $userData
     * @param $accompanyAbility
     * @param $accompanyGame
     * @return array
     */
    public function buildOrderData($order, $userData, $accompanyAbility, $accompanyGame, $isAnchor = 1)
    {
        return [
            'id'            => $order['id'],
            'user_id'       => $order['user_id'],
            'ability_id'    => $order['ability_id'],
            'anchor_id'     => $order['anchor_id'],
            'order_no'      => $order['order_no'],
            'service_time'  => $this->time($order['service_time']),
            'count'         => $order['count'],
            'price'         => $order['price'],
            'coupon_price'  => $order['coupon_price'],
            'total_price'   => $order['total_price'],
            'remark'        => $order['remark'],
            'status'        => $order['status'],
            'unit'          => $order['unit'],
            'status_name'   => $this->getStatusName($order, $isAnchor),
            'refund_status' => $order['refund_status'],
            'refund_id'     => $order['refund_id'],
            'created_at'    => $order->created_at->toDateTimeString(),
            'grade'         => $order['grade'],
            'comment'       => $order['comment'],
            'comment_label' => array_filter(explode(',', $order['comment_label'])),
            'profit'        => $order['profit'],
            'service_fee'   => $order['service_fee'],
            'can_comment'   => empty($order['grade']) && $order['status'] == 2 ? 1 : 0,
            'game_id'       => $accompanyAbility['game_id'],
            'game_name'     => $accompanyAbility['game_name'],
            'game_picture'  => $accompanyGame['picture'],
            'action_status' => $this->getActionStatus($order['status'], $order['grade']),
            'user_data'     => [
                'nickname'     => $userData['nickname'],
                'user_id'      => $userData['user_id'],
                'sex'          => $userData['sex'], // 性别
                'head_picture' => $userData['head_picture'], // 头像
            ],
        ];
    }

    /**
     * 获取当前订单状态
     * @return int
     */
    public function getActionStatus($status, $grade): int
    {
        if ($grade != 0) {
            return 2;
        }
        if (in_array($status, [-2, 2, 3])) {
            return 1;
        }
        return 0;
    }

    private function checkAbility($ability, $count, $userId, $couponId = 0, $checkOrderCount = true)
    {
        if ($count <= 0) {
            throw new BasicException(0, '数量有误');
        }
        if (empty($ability)) {
            throw new BasicException(0, '技能不存在');
        }
        if ($ability['price'] == 0) {
            throw new BasicException(0, '该陪玩未设置价格,不能下单');
        }
        if ($ability['user_id'] == $userId) {
            throw new BasicException(0, '不能给自己下单');
        }
        $dayTime = date('Y-m-d 00:00:00',time());
        if ($checkOrderCount) {
            //冥想订单用户只能对同一个人下两单
            if($ability['type'] == AccompanyEnum::ACCOMPANY_TYPE_MEDITATION){
                $orderCount = AccompanyOrder::query()->where('user_id',$userId)->where('type',AccompanyEnum::ACCOMPANY_TYPE_MEDITATION)->where('anchor_id',$ability['user_id'])->count();
                if ($orderCount > 1) {
                    $designation = '导师';
                    throw new BasicException(0, "最多对一个{$designation}下两单");
                }
            }else{
                $orderCount = AccompanyOrder::query()->where('user_id',$userId)->where('anchor_id',$ability['user_id'])->where('created_at','>',$dayTime)->count();
                if ($orderCount > 2) {
                    $designation = '主播';
                    throw new BasicException(0, "每天最多对一个{$designation}下三单");
                }
            }
        }
        $price = (int)$ability['price'] * $count;
        $coupon = new AccompanyCouponService();
        $couponInfo = $coupon->couponPrice($price, $userId, $couponId);
        //冥想不使用优惠卷
        if ($ability['type'] == AccompanyEnum::ACCOMPANY_TYPE_MEDITATION) {
            $couponInfo['reduced_price'] = 0;
            $couponInfo['id']            = 0;
        }
        $price = $price - $couponInfo['reduced_price'];
        if ($price < 0) {
            throw new BasicException(0, '价值有误');
        }
        return [
            'price' => $price,
            'couponInfo' => $couponInfo,
        ];
    }


    /**
     * @throws BasicException
     * @throws Exception
     */
    public function createOrder($abilityId, $count, $time, $remark, $userId, $couponId)
    {
        $ability = AccompanyAbility::query()->where('id', $abilityId)
            ->select(['id', 'user_id', 'game_name', 'game_id', 'game_level', 'game_service', 'grade', 'order_count', 'price', 'unit', 'type'])
            ->where('status', 1)
            ->first();
        $check = $this->checkAbility($ability, $count, $userId, $couponId);
        $price = $check['price'];
        $couponInfo = $check['couponInfo'];

        $coin = WalletRepository::getInstance()->userCoin($userId);
        if ($coin < $price) {
            throw new BasicException(330001, '余额不足');
        }
        DB::beginTransaction();
        try {
            $orderNo = $this->createOrderSn();
            $data = [
                'order_no'     => $orderNo,
                'user_id'      => $userId,
                'anchor_id'    => $ability['user_id'],
                'ability_id'   => $ability['id'],
                'service_time' => $time,
                'count'        => $count,
                'price'        => $ability['price'],
                'coupon_price' => $couponInfo['reduced_price'],
                'total_price'  => $price,
                'remark'       => $remark,
                'game_name'    => $ability['game_name'],
                'game_id'      => $ability['game_id'],
                'coupon_id'    => $couponInfo['id'],
                'status'       => 0,
                'unit'         => $ability['unit'],
                'user_news'    => 0,
                'anchor_news'  => 0,
                'type'         => $ability['type'],
            ];
            $data = AccompanyOrderRepository::getInstance()->create($data);
            // 钱包服务

            if ($couponInfo['id']) {
                AccompanyCouponUser::query()->where('id', $couponInfo['id'])->update([
                    'status'   => 1,
                    'order_id' => $data['id'],
                    'use_time' => date('Y-m-d H:i:s', time()),
                ]);
            }

            if ($price > 0) {
                WalletRepository::getInstance()->accompanyDecCoin($userId, $price, (int)$data['id']);
            }
            AccompanyOrderLogRepository::getInstance()->save($data['id'], 0, '用户创建订单', $userId);
            DB::commit();
            $this->sendCreateMessage($data['id']);
            dispatch((new AccompanyCancelJob($data['id']))->delay(self::endTime));
            //            dispatch($this->cancelOrder($data['user_id'],$data['id']))->delay(self::endTime);
            return $data;
        } catch (Exception $e) {
            DB::rollBack();
            return false;
        }

    }

    public function sendCreateMessage($id): bool
    {
        $data = AccompanyOrderRepository::getInstance()->orderDetail($id);
        //弹窗消息
        $cloud = new RongCloudService();
        $unit = $data['unit'];
        if ($data->type == AccompanyEnum::ACCOMPANY_TYPE_MEDITATION){
            $unit = '单';
        }
        $sendData = [
            'order_id' => $data['id'],
            'info'     => [
                'nickname'     => $data['nickname'] . '  给你下了订单',
                'game_picture' => $data['picture'],
                'game_name'    => $data['game_name'],
                'service_time' => $this->time($data['service_time']),
                'remark'       => $data['remark'],
                'total_price'  => '预计收入' . $data['total_price'] . '豆',
                'time'         => 15,
                'count'        => $data['count'],
                'unit'         => $unit,
            ],
        ];
        $res = [
            'name'    => 'cmd',
            'uni_key' => uniqidReal(),
            'data'    => [
                'msg'  => [
                    'content' => $sendData,
                ],
                'type' => PushChatService::CHAT_RECOMMEND_ACCOMPANY_ORDER,
                'time' => time(),
            ],
        ];
        $cloud->systemPushUser('system', 'user_' . $data['anchor_id'], $res);
        $designation = AccompanyEnum::ACCOMPANY_NAME[$data->type] ?? '';
        //私聊消息
        $content = '收到' . $data['game_name'] . '订单,请尽快确认';
        $this->shareUserMessage($content, '(' . self::endTime / 60 . '分钟未接单自动拒绝)', $data['anchor_id'], $data['user_id'], 1);
        $content = '对方已收到' . $data['game_name'] . '订单,将尽快确认';
        $this->shareUserMessage($content, "请等待{$designation}接单(" . self::endTime / 60 . "分钟未接单自动取消)", $data['user_id'], $data['anchor_id'], 0);
        return true;
    }

    public function shareUserMessage($content, $tips, $toSendId, $userId, $type)
    {

        $messageExt = [
            "user_id"    => $userId,
            "to_seng_id" => $toSendId,
            "tips"       => $tips,
            'content'    => $content,
            'status'     => $type,
        ];
        (new PushChatService($toSendId, 0))->accompanyMessage($userId, $toSendId, $messageExt);
        return Response::sendData([]);
    }

    /**
     * @param $id
     */
    public function orderDetail($id)
    {
        return AccompanyOrder::query()
            ->select([''])->where('id', $id)
            ->leftJoin('ln_accompany_ability as ab', 'ln_accompany_order.ab')
            ->first();
    }

    //生成订单号
    private function createOrderSn()
    {
        $orderSn = strtoupper(date('Ymd', time())) . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
        return $orderSn;
    }

    /**
     * 获取订单详情
     * @param $userId
     * @param $orderId
     * @return
     * @throws Exception
     */
    public function getDetail($userId, $orderId)
    {
        $order = AccompanyOrder::query()->with(['user_data', 'anchor', 'accompany_ability', 'accompany_game'])->where(['id' => $orderId])->first();
        if (empty($order)) {
            throw new BasicException(-1, '无此订单');
        }
        $userData = $order['user_data'];
        $anchor = $order['anchor'];
        $label = AccompanyLabel::query()->whereRaw("FIND_IN_SET(?,game_id)", [$order['game_id']])->get()->toArray();
        $orderRefund = AccompanyOrderRefund::query()->where(['order_id' => $orderId])->first();
        $orderRefundData = [];
        if (!empty($orderRefund)) {
            $orderRefundData['refund_id'] = $orderRefund->id;
            $orderRefundData['refund_reason'] = $orderRefund->refund_reason;
            $orderRefundData['refund_picture'] = empty($orderRefund->refund_picture) ? [] : explode(',', $orderRefund->refund_picture);
            $orderRefundData['refund_description'] = $orderRefund->refund_description;
            $orderRefundData['anchor_reason'] = $orderRefund->anchor_reason;
            $orderRefundData['anchor_picture'] = empty($orderRefund->anchor_picture) ? [] : explode(',', $orderRefund->anchor_picture);
            $orderRefundData['created_at'] = $orderRefund->created_at->toDateTimeString();
        }
        $endTime = time() - strtotime($order->created_at);
        $endTime = self::endTime - $endTime;
        $endTime = $endTime < 0 ? 0 : $endTime;
        if ($order->status > 0) {
            $endTime = 0;
        }
        $canRefund = 0;
        if ($order['refund_id'] ==0 && ($order['status'] == 1 || ($order['status'] == 2 && $order['accomplish_at'] > date('Y-m-d H:i:s',time() -24*3600)))){
            $canRefund = 1;
        }
        $data = [
            'id'                 => $order->id,
            'order_no'           => $order->order_no,
            'user_id'            => $order->user_id,
            'anchor_id'          => $order->anchor_id,
            'game_id'            => $order->game_id,
            'game_name'          => $order->game_name,
            'game_picture'       => $order['accompany_game']['picture'] ?? '',
            'service_time'       => $this->time($order->service_time),
            'count'              => $order->count,
            'price'              => $order->price,
            'coupon_price'       => $order->coupon_price,
            'total_price'        => $order->total_price,
            'remark'             => $order->remark,
            'ability_id'         => $order->ability_id,
            'status'             => $order->status,
            'unit'               => $order->unit,
            'can_refund'         => $canRefund,
            'refund_status'      => $order->refund_status,
            'took_at'            => $order->took_at,
            'created_at'         => $order->created_at->toDateTimeString(),
            'is_accompany_order' => ($userId == $order->anchor_id) ? 1 : 2, //  1 我的订单 2 我的下单,
            'end_time'           => $endTime,
            'action_status'      => $this->getActionStatus($order->status, $order->grade),
            'type'       => $order['accompany_game']['type'] ?? 0,
            'user_data'          => [
                'user_id'      => $userData['user_id'],
                'sex'          => $userData['sex'],
                'head_picture' => $userData['head_picture'],
                'nickname'     => $userData['nickname'],
                'mood'         => $userData['mood'],
                'is_accompany' => $userData['is_accompany'],
            ],
            'anchor'             => [
                'user_id'      => $anchor['user_id'],
                'sex'          => $anchor['sex'],
                'head_picture' => $anchor['head_picture'],
                'nickname'     => $anchor['nickname'],
                'mood'         => $anchor['mood'],
                'is_accompany' => $anchor['is_accompany'],
            ],
        ];


        $isAnchor = ($userId == $order->anchor_id) ? 1 : 0;
        return array_merge($data,
            [
                'status_name'  => $this->getStatusName($order, $isAnchor),
                'label_list'   => $label,
                'order_refund' => empty($orderRefundData) ? null : $orderRefundData,
            ]);
    }


    /**
     * 取消订单
     * @param $userId
     * @param $orderId
     * @return int
     * @throws Exception
     */
    public function cancelOrder($userId, $orderId)
    {
        $order = AccompanyOrder::query()->where(['id' => $orderId, 'user_id' => $userId])->first();
        if (empty($order)) {
            throw new BasicException(-1, '无此订单');
        }
        if ($order->status != 0) {
            throw new BasicException(-1, '订单状态已发生变化,不可取消');
        }
        DB::beginTransaction();
        try {
            $price = $order->total_price;
            WalletRepository::getInstance()->accompanyOrderCancel($order->user_id, $price, (int)$order->id, '用户取消陪玩单');
            // 订单是否使用优惠券-退还优惠券
            if ($order->coupon_id != 0) {
                $accompanyCouponUser = AccompanyCouponUser::query()->where(['id' => $order->coupon_id, 'user_id' => $userId])->first();
                if ($accompanyCouponUser) {
                    $accompanyCouponUser->status = 0;
                    $accompanyCouponUser->refund = $accompanyCouponUser->refund + 1;
                    $accompanyCouponUser->save();
                }
            }
            AccompanyOrder::query()->where(['id' => $orderId])->update(['status' => -3]);
            AccompanyOrderLogRepository::getInstance()->save($orderId, -3, '用户取消订单', $userId);
            DB::commit();
            return true;
        } catch (Exception $e) {
            DB::rollBack();
            throw new BasicException($e->getCode(), $e->getMessage());
        }
    }


    /**
     * 超时取消订单
     * @param $orderId
     * @return int
     * @throws BasicException
     */
    public function timeOutCancelOrder($orderId)
    {
        $order = AccompanyOrder::query()->where(['id' => $orderId])->first();
        if (empty($order)) {
            return true;
        }
        if ($order->status != 0) {
            return true;
        }
        DB::beginTransaction();
        try {
            $price = $order->total_price;
            WalletRepository::getInstance()->accompanyOrderCancel($order->user_id, $price, (int)$order->id, '超时取消订单');
            // 订单是否使用优惠券-退还优惠券
            if ($order->coupon_id != 0) {
                $this->returnCoupon($order->user_id,$order->coupon_id);
            }
            AccompanyOrder::query()->where(['id' => $orderId])->update(['status' => -4]);

            AccompanyOrderLogRepository::getInstance()->save($orderId, -4, '超时取消订单');
            DB::commit();
            $yesterday = date('Y-m-d 00:00:00',strtotime('-1 day'));
            $today     = date('Y-m-d H:i:s',time());
            $data      = AccompanyOrderRepository::getInstance()->getUserByDateAndStatusData($order->anchor_id, $yesterday, $today, -4);
            $key       = 'user:accompany:order:ban:' . $order->anchor_id;
            if (!empty($data) && count($data) >= 2 && !app('redis')->get($key)) {
                app('redis')->set($key, $order->anchor_id, 'ex',7 * 86400);
            }
            return true;
        } catch (Exception $e) {
            DB::rollBack();
            throw new BasicException($e->getCode(), $e->getMessage());
        }
    }


    /**
     * 退还优惠卷
     * @param $userId
     * @param $couponId
     *
     * @return bool
     */
    public function returnCoupon($userId,$couponId): bool
    {
        $accompanyCouponUser = AccompanyCouponUser::query()->where(['id' => $couponId, 'user_id' => $userId])->first();
        if ($accompanyCouponUser) {
            $accompanyCouponUser->status = 0;
            $accompanyCouponUser->refund = $accompanyCouponUser->refund + 1;
            $accompanyCouponUser->save();
        }
        return true;
    }

    /**
     * 获取当前订单状态
     * @param $order
     * @param int $isAnchor
     * @param bool $flag
     * @return string
     */
    public function getStatusName($order, $isAnchor = 1, $flag = false): string
    {
        $anchorStatusArr = [
            '-4' => '已拒绝',
            '-3' => '已拒绝',
            '-2' => '已退款',
            '-1' => '已拒绝',
            '0'  => '待接单',
            '1'  => '进行中',
            '2'  => '已完成',
            '3'  => '已结算',
        ];
        $statusArr = [
            '-4' => '已取消',
            '-3' => '已取消',
            '-2' => '已退款',
            '-1' => '已关闭',
            '0'  => '待接单',
            '1'  => '进行中',
            '2'  => '已完成',
            '3'  => '已结算',
        ];
        $userStatusName = $statusArr[(string)$order['status']] ?? '';
        $anchorStatusName = $anchorStatusArr[(string)$order['status']] ?? '';
        $statusName = $isAnchor == 1 ? $anchorStatusName : $userStatusName;

        if(in_array($order['status'], [2, 3]) && $order["grade"] > 0){
            $statusName = "已评价";
        }
        if($flag && in_array($order['status'], [2, 3]) && $order["grade"] == 0){
            $statusName = "评价";
        }

        if (!empty($order['refund_id'])) {
            $refundStatus = $order['refund_status'];
            if ($refundStatus == -1 || $refundStatus == -3) {
                $statusName = '拒绝退款';
            } elseif ($refundStatus == 0 || $refundStatus == -2 || $refundStatus == -1) {
                $statusName = '退款中';
            } elseif ($refundStatus == 1 || $refundStatus == 2 ) {
                $statusName = '已退款';
            }
        }


        return $statusName;
    }

    /**
     * 订单添加评价
     * @param $userId
     * @param $orderId
     * @param $comment
     * @param $label
     * @param $grade
     * @return int
     * @throws Exception
     */
    public function comment($userId, $orderId, $comment, $label, $grade)
    {
        $order = AccompanyOrder::query()->where(['id' => $orderId, 'user_id' => $userId])->first();
        if (empty($order)) {
            throw new BasicException(-1, '无此订单');
        }
        if ($grade < 0 || $grade > 5) {
            throw new BasicException(-1, '参数不合法');
        }
        if ($order->grade > 0) {
            throw new BasicException(-1, '订单已评价');
        }
        if (empty($order->room_demand_id)) {
            $accompanyAbility = AccompanyAbility::query()->where(['id' => $order->ability_id])->first();
            if (empty($accompanyAbility)) {
                throw new BasicException(-1, '陪玩技能不存在');
            }

            //$avgGrade = $this->getAnchorAvgGrade($order->anchor_id);
            $gradeAvg = ($grade + $accompanyAbility->grade)/2;
            $avgGrade = round($gradeAvg, 1);
            AccompanyAbility::query()->where(['id' => $order->ability_id])->update(['grade' => $avgGrade,]);
        }

        $label = empty($label) ? '' : implode(',', array_filter($label));
        AccompanyOrder::query()->where(['id' => $orderId])->update([
            'comment'       => $comment,
            'grade'         => $grade,
            'comment_label' => $label,
        ]);
        return true;
    }


    /**
     * 获取用户平均分
     * @param $anchorId
     * @return mixed
     */
    public function getAnchorAvgGrade($anchorId)
    {
        $grade = 0;
        $avgGrade = AccompanyOrder::query()->where(['anchor_id' => $anchorId])->whereIn('status', [-2, 1, 2, 3])->where('grade','>',0)->avg('grade');
        if (!empty($avgGrade)) {
            $grade = round($avgGrade, 1);
        }
        return $grade;
    }

    public function userMessage($userId, $anchorId)
    {

        //用户侧
        $ownOrder = AccompanyOrderRepository::getInstance()->messageOrder($userId, $anchorId)->toArray();
        foreach ($ownOrder as &$value) {
            $value['bottom'] = 0;
            $value['last_time'] = 0;
            if ($value['status'] == 0) {
                $value['content'] = '对方确认订单中';
                $value['bottom'] = 4; //取消订单按钮
                $time = strtotime($value['created_at']) + self::endTime - time();
                $value['last_time'] = ($time > 0) ? $time : 0;
            } elseif ($value['status'] == 1) { //订单进行中
                $value['content'] = '请确保服务结束后完成订单';
                $value['bottom'] = 1;   //完成订单按钮
            } elseif ($value['status'] > 1 && $value['grade'] == '0.0') {
                $value['content'] = '本次游戏达人订单已结束，快去评价TA的...';
                $value['bottom'] = 2;  //立即评价按钮
            } else {
                $value['content'] = '本次游戏达人订单已结束';
            }
            $value['time'] = $this->time($value['service_time']);
            $value['end_time'] = strtotime($value['created_at']) + self::endTime - time();
        }

        //达人侧
        $anchorOrder = AccompanyOrderRepository::getInstance()->messageOrder($anchorId, $userId)->toArray();
        foreach ($anchorOrder as &$v) {
            $v['bottom'] = 0;
            $v['last_time'] = 0;
            if ($v['status'] == 0) {
                $v['content'] = '对方给你下了订单，请尽快确认';
                $v['bottom'] = 3;  //同意和拒绝按钮
                $time = strtotime($v['created_at']) + self::endTime - time();
                $v['last_time'] = ($time > 0) ? $time : 0;
            } elseif ($v['status'] == 1) {
                $v['content'] = '等待对方确认订单';
            } elseif ($v['status'] == 2) {
                $v['content'] = '本次游戏达人订单已结束，收益将在订单完成24小时后结算进入收益';
            } else {
                $v['content'] = '本次游戏达人订单已结束';
            }
            $v['time'] = $this->time($v['service_time']);
            $v['end_time'] = (strtotime($v['created_at']) + self::endTime) - time();
        }
        $data = array_merge($anchorOrder,$ownOrder);
        $sort = array_column($data,'id');
        array_multisort($sort,SORT_DESC,$data);
        return array_values($data);


    }

    public function time($time)
    {
        $time = strtotime($time);
        $today = strtotime(date('Y-m-d'));
        $yesterday = strtotime('-1 days',$today);
        $beforeYesterday = strtotime('-2 days',$today);
        switch ($time) {
            case $today <= $time:
                $fdate = '今天' . date('H:i', $time);
                break;
            case $yesterday <= $time:
                $fdate = '昨天' . date('H:i', $time);
                break;
            case $beforeYesterday <= $time:
                $fdate = '前天' . date('H:i', $time);
                break;
            default:
                $fdate = date('m-d H:i', $time);
                break;
        }
        return $fdate;
    }

    public function getTime($time){
        $time = strtotime($time);
        $today = strtotime(date('Y-m-d'));
        $yesterday = strtotime('-1 days',$today);
        $beforeYesterday = strtotime('-2 days',$today);
        switch ($time) {
            case $today <= $time:
                $fdate = '今天' . date('H:i', $time);
                break;
            case $yesterday <= $time:
                $fdate = '昨天' . date('H:i', $time);
                break;
            case $beforeYesterday <= $time:
                $fdate = '前天' . date('H:i', $time);
                break;
            default:
                $fdate = date('m-d H:i', $time);
                break;
        }
        return $fdate;
    }

    public function refuseOrder($orderId, $userId)
    {
        $order = AccompanyOrder::query()->where(['id' => $orderId, 'anchor_id' => $userId])->first();
        if (empty($order)) {
            throw new BasicException(-1, '无此订单');
        }
        if ($order['status'] != 0) {
            throw new BasicException(-1, '此订单已经处理过了');
        }
        DB::beginTransaction();
        try {
            $res = AccompanyOrder::query()->where(['id' => $orderId])->update(['status' => -1]);
            $price = $order->total_price;
            WalletRepository::getInstance()->accompanyOrderCancel($order->user_id, $price, (int)$order->id, '达人拒绝接单');
            AccompanyOrderLogRepository::getInstance()->save($orderId, -1, '达人拒绝接单', $userId);
            if ($order['coupon_id'] != 0) {
                $this->returnCoupon($order['user_id'], $order['coupon_id']);
            }

            DB::commit();
            //私聊消息
            $content = '对方已拒绝' . $order['game_name'] . '订单！';
            $this->shareUserMessage($content, '请与对方再商量', $order['user_id'], $order['anchor_id'], 0);
            $content = '您已拒绝' . $order['game_name'] . '订单！';
            $this->shareUserMessage($content, '请与对方再商量', $order['anchor_id'], $order['user_id'], 1);

            $yesterday = date('Y-m-d 00:00:00',strtotime('-1 day'));
            $today     = date('Y-m-d H:i:s',time());
            $data      = AccompanyOrderRepository::getInstance()->getUserByDateAndStatusData($userId, $yesterday, $today, -1);
            $key       = 'user:accompany:order:ban:' . $userId;
            if (!empty($data) && count($data) >= 2 && !app('redis')->get($key)) {
                app('redis')->set($key, $userId, 'ex',7 * 86400);
            }
            return $res;
        } catch (Exception $e) {
            DB::rollBack();
            throw new BasicException($e->getCode(), $e->getMessage());
        }
    }

    public function acceptOrder($orderId, $userId)
    {
        $order = AccompanyOrder::query()->where(['id' => $orderId, 'anchor_id' => $userId])->first();
        if (empty($order)) {
            throw new BasicException(-1, '无此订单');
        }
        if ($order['status'] != 0) {
            throw new BasicException(-1, '此订单已经处理过了');
        }
        $accompanyAbility = AccompanyAbility::query()->where(['id' => $order->ability_id])->first();
        if (empty($accompanyAbility)) {
            throw new BasicException(-1, '陪玩技能不存在');
        }

        $dayTime  = date('Y-m-d', time());
        $dayCount = AccompanyOrder::query()->where('anchor_id', $userId)
            ->whereIn('status', [-2, 1, 2, 3, 4])
            ->where('room_demand_id', 0)
            ->where('created_at', '>', $dayTime)->count();
        if ($dayCount > 9) {
            throw new BasicException(-1, '单日最多接10单');
        }
        $time = date('Y-m-d H:i:s', time() - 3600);
        $count = AccompanyOrder::query()->where('anchor_id', $userId)
            ->where('status',1)
            ->where('room_demand_id', 0)
            ->where('created_at', '>', $time)->count();
        if ($count > 4) {
            throw new BasicException(-1, '一小时内最多接五单');
        }
        // 计算订单收益
        if ($order->type == AccompanyEnum::ACCOMPANY_TYPE_MEDITATION) {
            $orderProfit = $this->calculateOrderProfitMeditation($order->total_price);
        } else {
            $orderProfit = $this->calculateOrderProfit($order->total_price);
        }

        // 更新用户的接单次数
        AccompanyAbility::query()->where(['id' => $order->ability_id])->update(['order_count' => $accompanyAbility->order_count + 1]);
        $res = AccompanyOrder::query()->where(['id' => $orderId])
            ->update([
                'status'      => 1,
                'took_at'     => date('Y-m-d H:i:s'),
                'profit'      => $orderProfit['profit'],
                'service_fee' => $orderProfit['service_fee'],
            ]);

        AccompanyOrderLogRepository::getInstance()->save($orderId, 1, '达人接收订单', $userId);
        //私聊消息
        $content = '对方已确认' . $order['game_name'] . '订单！';
        $userMessage = '请与大神商量服务时间（24小时不处理将会自动完成并结算）';
        $toUserMessage = '请向对方询问游戏具体区服及昵称进行服务';
        if ($order->type == 1){
            $userMessage = '请与导师商量服务时间（24小时不处理将会自动完成并结算）';
            $toUserMessage = '请尽快与对方沟通';
        }
        $this->shareUserMessage($content, $userMessage, $order['user_id'], $order['anchor_id'], 0);
        $content = '您已确认' . $order['game_name'] . '订单！';
        $this->shareUserMessage($content, $toUserMessage, $order['anchor_id'], $order['user_id'], 1);
        dispatch((new AccompanyFinishJob($orderId))->delay(self::FINISH_TIME));
        return $res;
    }

    /**
     * 获取用户进行中的订单
     * @param $userId
     * @return array
     */
    protected function getUserOngoingOrder($userId)
    {
        $data = [];
        $onGoingOrderArr = AccompanyOrder::query()
            ->with(['user_data', 'anchor', 'accompany_ability', 'accompany_ability.accompany_game'])
            ->where(['user_id' => $userId])
            ->whereIn('status', [0, 1,2])
            ->where(function ($query){
                $query->where('accomplish_at', '>', date('Y-m-d H:i:s', time() - 24 * 3600))
                    ->orWhereNull('accomplish_at');
            })
            ->where('grade','==','0.0')
            ->orderBy('created_at', 'desc')
            ->get();
        foreach ($onGoingOrderArr as $order) {
            $data[] = $this->buildOrderData($order, $order['anchor'], $order['accompany_ability'], $order['accompany_ability']['accompany_game'], 0);
        }
        return $data;
    }

    /**
     * 获取陪玩进行中的订单
     * @param $userId
     * @return array
     */
    protected function getAnchorOngoingOrder($userId)
    {
        $data = [];
        $onGoingOrderArr = AccompanyOrder::query()
            ->with(['user_data', 'anchor', 'accompany_ability', 'accompany_ability.accompany_game'])
            ->where(['anchor_id' => $userId])
            ->whereIn('status',[0, 1, 2])
            ->where(function ($query){
                $query->where('accomplish_at', '>', date('Y-m-d H:i:s', time() - 24 * 3600))
                    ->orWhereNull('accomplish_at');
            })
            ->where('grade','==','0.0')
            ->orderBy('created_at', 'desc')
            ->get();
        foreach ($onGoingOrderArr as $order) {
            $data[] = $this->buildOrderData($order, $order['user_data'], $order['accompany_ability'], $order['accompany_ability']['accompany_game']);
        }
        return $data;
    }

    /**
     * 计算游戏订单收益和分成
     * @param $totalPrice
     * @param $config_value
     * @return array
     */
    public function calculateOrderProfit($totalPrice, $config_value = 'ACCOMANY_INCOME_SHARING', $is_role = 0)
    {
        // $profit = 0;
        // $serviceFee = 0;
        $val = (new Config())->getValue($config_value);
        // if (empty($val) || $val <= 0) {
            // $profit = $totalPrice;
        // }
        $fanliFee = $fromFanliFee= 0;
        if (is_numeric($val)) {
            $profit = bcmul($totalPrice, $val / 100, 2);
            $serviceFee = bcsub($totalPrice, $profit, 2);
        } else {
            $val_data = explode(',', $val);
            if ($is_role) {
                $profit = bcmul($totalPrice, $val_data[1] / 100);
            } else {
                $profit = bcmul($totalPrice, $val_data[0] / 100);
            }
            $fromFanliFee = bcmul($totalPrice, $val_data[2] / 100);
            $fanliFee = bcmul($totalPrice, $val_data[3] / 100);
            $serviceFee = bcsub($totalPrice, $profit + $fanliFee + $fromFanliFee);
        }
        return [
            'profit'      => $profit,//主播收益
            'service_fee' => $serviceFee,//服务费
            'from_fanli_fee' => $fromFanliFee,//来源返利
            'fanli_fee' => $fanliFee,//返利
        ];
    }
    /**
     * 计算冥想订单收益和分成
     * @param $totalPrice
     * @return array
     */
    public function calculateOrderProfitMeditation($totalPrice): array
    {
        // $profit = 0;
        // $serviceFee = 0;
        $val = (new Config())->getValue('ACCOMPANY_INCOME_MEDITATION');
        if (empty($val) || $val <= 0) {
            $profit = $totalPrice;
        }
        $profit = bcmul($totalPrice, $val / 100, 2);
        $serviceFee = bcsub($totalPrice, $profit, 2);
        return [
            'profit'      => $profit,
            'service_fee' => $serviceFee,
        ];
    }

    /**
     * 是否可以下单
     * @param $userId
     * @return int
     */
    public function getCanOrder($userId)
    {
        $canOrder = 1;
        // 后台配置是否可以下单
        $orderEnableConfig = (new Config())->getValue('ACCOMPANY_ORDER_ENABLE');
        if ($orderEnableConfig == 0) {
            return 0;
        }
        // 判断当前用户是否在不可下单的地区
        $userRegion = (new Config())->getValue('ACCOMPANY_REGION_CONFIG');
        // $userRegion = Config::query()->where(['key'=>'ACCOMPANY_REGION_CONFIG','status'=>0])->value('value');
        if (!empty($userRegion)) {
            $userRegion = explode(',', $userRegion);
            $userRegionArr = Region::query()->whereIn('region_name', $userRegion)->pluck('id')->toArray();
            $userDevice = UserData::query()->where(['user_id' => $userId])->orderBy('id', 'desc')->first();
                if (in_array($userDevice['current_city_id'], $userRegionArr)) {
                    $canOrder = 0;
            }
        }
        return $canOrder;
    }

    /**
     * 完成订单
     * @param $userId
     * @param $orderId
     * @return int
     * @throws Exception
     */
    public function orderFinish($orderId)
    {
        $order = AccompanyOrder::query()->where(['id' => $orderId])->first();
        if (empty($order)) {
            return true;
        }
        if ($order->status != 1) {
            return true;
        }
        DB::beginTransaction();
        try {
            AccompanyOrder::query()->where(['id' => $orderId])->update(
                ['status' => 2,
                    'accomplish_at'=> date('Y-m-d H:i:s', time()),
                ]);

            AccompanyOrderLogRepository::getInstance()->save($orderId, '2', '超时订单完成');
            DB::commit();

            // TaskRepository::getInstance()->order((int)$order->userId);
            return true;
        } catch (Exception $e) {
            DB::rollBack();
            throw new BasicException($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 完成订单
     * @param $orderId
     * @param $userId
     * @return int
     * @throws BasicException
     * @throws Exception
     */
    public function accomplishOrder($orderId, $userId): int
    {
        $order = AccompanyOrder::query()->with(['user_data', 'anchor', 'user_room'])->where(['id' => $orderId, 'user_id' => $userId])->first();
        if (empty($order)) {
            throw new BasicException(-1, '无此订单');
        }
        if ($order->status != 1) {
            throw new BasicException(-1, '订单状态已发生变化,不可取消');
        }
        DB::beginTransaction();
        try {
            $res = AccompanyOrder::query()->where(['id' => $orderId])->update(
                ['status'        => 2,
                 'accomplish_at' => date('Y-m-d H:i:s', time())
                ]);
            $repository = WalletRepository::getInstance()/*->setClientIP(get_real_ip())*/;
            $price = $order->profit;
            $repository->accomplishOrder($order->anchor_id, $price, (int)$order->id, '完成订单,进行收益');
            //订单返利  给来源房间的厅主
            if (!empty($order->room_demand_id)) {
                $user_room_id = $order->user_room->room_id;
                $desc = "游戏订单：日返 房间ID:{$user_room_id} {$order->user_data->user_code}下单给{$order->anchor->user_code}";
                if ($order->from_fanli_fee > 0 && !empty($order->from_room_id)) {
                    $from_hall_user_id = app('model_sc_hall')->where('room_id', $order->from_room_id)->value('user_id');
                    if ($from_hall_user_id) {
                        app('repo_user')->updateUserEarnings([
                            'user_id' => $from_hall_user_id,
                            'money'   => $order->fanli_fee,
                        ]);
                        app('model_account_log')->addLog($from_hall_user_id, $order->from_fanli_fee, $desc, 234, $order->id, $order->room_id);
                    }
                }
                if ($order->fanli_fee > 0 && !empty($order->room_id)) {
                    $room = RedisService::getRoomDetailByRoomId($order->room_id);
                    $sociatyInfo = app('model_sc_hall')->getSociatyInfo($order->room_id);
                    $union_user_id = $room['union_type'] == 1 ? 'hall_user_id' : 'user_id'; //日返类型 1返给厅主 2会长
                    $hall_user_id = $sociatyInfo[$union_user_id];
                    if ($hall_user_id) {
                        app('repo_user')->updateUserEarnings([
                            'user_id' => $hall_user_id,
                            'money'   => $order->fanli_fee,
                        ]);
                        $desc = "游戏订单：日返 房间ID:{$user_room_id} {$order->user_data->user_code}下单给{$order->anchor->user_code}";
                        app('model_account_log')->addLog($hall_user_id, $order->fanli_fee, $desc, 234, $order->id, $order->room_id);
                    }
                }
            }
            AccompanyOrderLogRepository::getInstance()->save($orderId, '2', '订单完成', $userId);
            DB::commit();
            //私聊消息
            $content = '您已选择完成' . $order['game_name'] . '订单，订单结束';
            $this->shareUserMessage($content, '本次订单已结束，去评价一下TA的服务吧！', $order['user_id'], $order['anchor_id'], 0);
            $content = '对方已选择完成订单，订单结束';
            $this->shareUserMessage($content, '本次订单已结束，收益将在订单完成24小时后结算进入收益', $order['anchor_id'], $order['user_id'], 1);

            // TaskRepository::getInstance()->order((int)$userId);
            return $res;
        } catch (Exception $e) {
            DB::rollBack();
            throw new BasicException($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 完成的订单24小时之后给收益
     * @return boolean
     */
    public function profitOrderCommand()
    {
        $order = AccompanyOrder::query()->where('status', 2)
            ->where('accomplish_at', '<', date('Y-m-d H:i:s', time() - 24 * 3600))->get();


        /*$fromRoomIds = array_unique(array_column($order->toArray(), 'from_room_id'));
        //查询该房间是否为公会厅 是：返利
        $hall_model = app('model_sc_hall');
        $hall_rooms = $hall_model->from($hall_model->getTable(). ' as a')
            ->join(app('model_sc_sociaty')->getTable().' as b','b.id', '=', 'a.sociaty_id')
            ->whereIn('room_id', $fromRoomIds)
            ->where(['a.status' => 3, 'b.status' => 3])
            ->selectRaw('b.user_id, a.room_id, a.user_id hall_user_id')
            ->get()->toArray();
        $hall_rooms = array_column($hall_rooms, NULL, 'room_id');*/
        foreach ($order as $value) {
            AccompanyOrder::query()->where('id', $value['id'])
                ->update([
                    'profit_at'=>date('Y-m-d H:i:s', time()),
                    'status' => 3,
                ]);
            /*if ($value['profit'] > 0){
                WalletRepository::getInstance()->accomplishOrder($value['anchor_id'], (int)$value['profit'], $value['id'],  '用户下单，获得收益');
                $this->shareUserMessage('收益发放', '收益发放', $order['anchor_id'], $order['user_id'], 1);
                AccompanyOrderLogRepository::getInstance()->save($value['id'], '3', '收益发放');
            }*/
            //派单 订单返利
            /*$hall_room = $hall_rooms[$value['from_room_id']] ?? [];
            if ($value['service_fee'] > 0 && $value['room_demand_id'] > 0 && !empty($hall_room)) {
                WalletRepository::getInstance()->accomplishOrder($hall_room['hall_user_id'], (int)$value['service_fee'], $value['id'],  '用户下单返利，获得收益');
                AccompanyOrderLogRepository::getInstance()->save($value['id'], '3', '返利发放');
                //删除相关的rediskey
                app('redis')->del(sprintf(AccompanyEnum::ROOM_DEMAND, $value['room_demand_id']));
                app('redis')->hdel(AccompanyEnum::DEMAND_COMPLETE, $value['room_demand_id']);
            }*/
        }
        return true;


    }

    /**
     * 定时任务取消订单
     * @return bool|void
     * @throws BasicException
     */
    public function cancelOrderCommand()
    {
        //派单房陪玩订单不自动取消
        $order = AccompanyOrder::query()->where('status', 0)->where('room_demand_id', 0)
            ->where('created_at', '<', date('Y-m-d H:i:s', time() - self::endTime))->get();

        foreach ($order as $value) {
            DB::beginTransaction();
            try {
                $price = $value['total_price'];
                WalletRepository::getInstance()->accompanyOrderCancel($value['user_id'], $price, (int)$value['id'], '超时取消订单');
                // 订单是否使用优惠券-退还优惠券
                if ($value['coupon_id'] != 0) {
                    $this->returnCoupon($value['user_id'],$value['coupon_id']);
                }
                AccompanyOrder::query()->where(['id' => $value['id']])->update(['status' => -4]);

                AccompanyOrderLogRepository::getInstance()->save($value['id'], '-4', '超时取消订单');
                DB::commit();
            } catch (Exception $e) {
                DB::rollBack();
                throw new BasicException($e->getCode(), $e->getMessage());
            }
        }

    }

    /**
     * 定时完成订单
     * @return boolean
     * @throws Exception
     */
    public function accomplishOrderCommand()
    {
        $order = AccompanyOrder::query()->where('status', 1)
            ->where('service_time', '<', date('Y-m-d H:i:s', time() - self::FINISH_TIME))->get();
        foreach ($order as $value) {
            $this->orderFinish($value['id']);
        }
        return true;

    }

    /**
     * 自动退款
     * @return void
     * @throws BasicException
     */
    public function refundOrderCommand(){
        $order=AccompanyOrder::query()->where('refund_status',0)->where('refund_id','>',0)
            ->where('create_refund_time','<', date('Y-m-d H:i:s', time() - 24*3600))
            ->get();
        $refund =new AccompanyOrderRefundService();

        foreach ($order as $value){
            $refund->refundAgree($value['anchor_id'],$value['id'],1);
        }

    }


    /**
     * @param $userId
     * @param $userToId
     *
     * @return bool
     * @throws Exception
     */
    public function sendBrowseMessage($userId, $userToId, $user = null,$type = 0)
    {
        if(!$user){
            $user = UserData::query()->where('user_id', $userId)->first();
        }
        //弹窗消息
        $cloud    = new RongCloudService();
        $info = $user['nickname'] . '  正在浏览你的游戏资料，主动联系他吧';
        //私聊消息
        $content = '正在浏览你的游戏资料，主动联系TA吧';
        if ($type == AccompanyEnum::ACCOMPANY_TYPE_MEDITATION) {
            $info    = $user['nickname'] . '正在查看通过冥想浏览你的资料，快去联系TA吧';
            $content = '正在浏览你的冥想资料，主动联系TA吧';
        }
        $sendData = [
            'user' => [
                'info'          => $info,
                'user_id'       => $user['user_id'],
                'head_picture'  => $user['head_picture'],
                'dress_picture' => RedisService::getHeadPicture($user['user_id']),//头像框
            ],
        ];
        $res      = [
            'name'    => 'cmd',
            'uni_key' => uniqidReal(),
            'data'    => [
                'msg'  => [
                    'content' => $sendData,
                ],
                'type' => PushChatService::CHAT_RECOMMEND_BROWSE_ACCOMPANY_MESSAGE,
                'time' => time(),
            ],
        ];
        $cloud->systemPushUser('system', 'user_' . $userToId, $res);


        $this->BrowseMessage($content, '', $userToId, $userId, 1);
        return true;
    }

    public function BrowseMessage($content, $tips, $toSendId, $userId, $type)
    {

        $messageExt = [
            "user_id"    => $userId,
            "to_seng_id" => $toSendId,
            "tips"       => $tips,
            'content'    => $content,
            'status'     => $type,
        ];
        (new PushChatService($toSendId, 0))->accompanyBrowseMessage($userId, $toSendId, $messageExt);
        return Response::sendData([]);
    }

    public function verifyAnchorOrderChat($orderId){
        $order = AccompanyOrder::query()->where(['id' => $orderId])->first();
        if (empty($order)) {
            return true;
        }
        $push = new PushService(0, 0);
        try {
            if($order->type == AccompanyEnum::ACCOMPANY_TYPE_MEDITATION){
                $chat = Chat::query()->where('user_id', $order->anchor_id)->where('user_id_to', $order->user_id)->where('add_time', '>=', strtotime($order->service_time))->first();
                if ($order->status == 1) {
                    if (empty($chat)) {
                        AccompanyOrder::query()->where(['id' => $orderId])->update(['status' => -2]);
                        $price      = $order->total_price;
                        WalletRepository::getInstance()->anchorUnChatRefund($order->user_id, $price, (int)$order->id, '主播订单未回复退款');
                        AccompanyOrderLogRepository::getInstance()->save($orderId, -4, '主播订单未回复退款', $order->anchor_id);
                        // 订单是否使用优惠券-退还优惠券
                        if ($order->coupon_id != 0) {
                            $this->returnCoupon($order->user_id, $order->coupon_id);
                        }
                        $push->accompanyOrderUnChat($order->user_id, $order->anchor_id, 1);
                    }
                } elseif ($order->status == -1||$order->status == -4) {
                    $push->accompanyOrderUnChat($order->user_id, $order->anchor_id, 1);
                }
            }
            return true;
        } catch (Exception $e) {
            throw new BasicException($e->getCode(), $e->getMessage());
        }
    }

    //派单需求
    public function sendDemand($params, $userId)
    {
        $remark = trim($params['remark'] ?? '');
        $level_name = $params['level_name'] ?? '';
        $service_name = $params['service_name'] ?? '';
        $room_demand = app('model_room_demand');
        $demand_count = $room_demand->where(['room_id' => $params['room_id']])->whereNotIn('status', [1, 2])->count();
        if (!empty($demand_count)) {
            throw new BasicException(-1, '房间还有未处理完的需求');
        }
        $model_accompany_game = app('model_accompany_game');
        $game = $model_accompany_game->where('id', $params['game_id'])->first();
        if ($game->price > $params['price']) {
            throw new BasicException(-1, "{$game->name}最低价格为{$game->price}金币");
        }
        $user_id_boss = RedisService::getOnPitUserId($params['room_id'], 10);
        if (empty($user_id_boss)) {
            throw new BasicException(-1, '老板不在麦上或者已掉麦');
        }

        $demand_id = $room_demand->insertGetId([
            'game_id'       => $params['game_id'],
            'user_id'       => $userId,
            'user_id_boss'  => $user_id_boss,
            'room_id'       => $params['room_id'],
            'gender'        => $params['gender'],
            'price'         => $params['price'],
            /*'price_from'    => $params['price_from'],
            'price_to'      => $params['price_to'],*/
            'service_name'  => $service_name,
            'level_name'    => $level_name,
            'remark'        => $remark,
            'status'        => 0,
        ]);

        //推送内容
        $sendData = [
            'demand_id'     => $demand_id,
            'room_id'       => $params['room_id'],
            'game_id'       => $params['game_id'],
            'game_name'     => $game->name,
            'gender'        => $params['gender'],
            'service_name'  => $service_name,
            'level_name'    => $level_name,
            'remark'        => $remark,
            'price'         => $params['price'],
            'price_area'    => $params['price']. '金币/'. $game->unit,
            'unit'          => $game->unit,
        ];
        //推送给主播  匹配 品类+性别+在房间内的主播
        $where = [
            'a.type'    => 0,
            'a.status'  => 1,
            ['c.room_id', '>', 0],
        ];

//        if (!empty($params['game_id'])) {
//            $where['a.game_id'] = $params['game_id'];
//        }
//        if (!empty($params['gender'])) {
//            $where['b.sex'] = $params['gender'];
//        }
        $model = app('model_accompany_ability');
        $pushUserIds = $model->from($model->getTable().' as a')
            ->join(app('model_user_data')->getTable(). ' as b', 'a.user_id', '=', 'b.user_id')
            ->join(app('model_room_online_user')->getTable(). ' as c', 'a.user_id', '=', 'c.user_id')
            ->where($where)->distinct()
            ->selectRaw("CONCAT('user_', a.user_id) as user_id")->get()->toArray();
        $pushUserIds = array_column($pushUserIds, 'user_id');
        if (!empty($pushUserIds)) {
            $pushObj = new PushService();
            $pushObj->roomDemandToAnchor($sendData, $pushUserIds);
        }

        $pushObj = new PushService(0, $params['room_id']);
        $sendData['status'] = 0;
        $pushObj->roomDemandUpdate($sendData);

        //获取该房间的需要下麦的用户 1-8全部下麦 9-10留下
        $down_pit_user = RedisService::getOnPitUserId($params['room_id']);
        unset($down_pit_user[9], $down_pit_user[10]);
        $room_param = ['room_id' => $params['room_id'], 'embrace' => 0];
        $secret_1 = env('ROOM_SECRET_NEW');
        $secret_2 = env('ROOM_SECRET');
        $url = env('ROOM_URL') . '/api/seat/down';
        foreach ($down_pit_user as $pit => $pit_user_id) {
            $room_param['pit_number'] = $pit;
            $room_sign = getSign($room_param, $secret_1, $secret_2);
//            $token = JwtService::createAndSaveToken($pit_user_id);
            $token = app('model_user_token')->where('user_id', $pit_user_id)->value('token');
            send_post_curl($url, $room_param, ['token:' . $token, 'sign:'.$room_sign]);
        }

        return [
            'demand_id' => $demand_id,
        ];

    }

    //发送订单确认
    public function sendDemandOrder($params, $userId)
    {
        $model_room_demand = app('model_room_demand');
        $demand = $model_room_demand->with('user_room')->where('id', $params['demand_id'])->first();
        if (empty($demand)) {
            throw new BasicException(-1, '该需求不存在');
        }
        $order_info = $params['order_info'];
        /*$ability_ids = array_column($order_info, 'ability_id');
        $user_abilitys = app('model_accompany_ability')
            ->whereIn('id', $ability_ids)
            ->select(['id', 'user_id', 'game_name', 'game_id', 'game_level', 'game_service', 'grade', 'order_count', 'price', 'unit', 'type'])
            ->where(['status' => 1, 'type' => 0])
            ->get()->toArray();
        $user_abilitys = array_column($user_abilitys, NULL, 'id');
        if (empty($user_abilitys)) {
            throw new BasicException(-1, '技能不存在');
        }*/
        $user_room = $demand->user_room;
        $check_total_price = 0;
        $time = time();
        $date_at = date('Y-m-d H:i:s');
        $insertAll = [];
        $accompany_game = app('model_accompany_game')->where('id', $demand->game_id)->first();
        if (empty($accompany_game)) {
            throw new BasicException(-1, '游戏id错误');
        }
        foreach ($order_info as $order) {
//            if (isset($user_abilitys[$order['ability_id']])) {
                /*$ability = $user_abilitys[$order['ability_id']];
                $ary = $this->checkAbility($ability, $order['count'], $userId, 0, false);
                $couponInfo = $ary['couponInfo'];*/
                $price = $demand->price;//取创建需求时定下的单价
                $total_price = $price * $order['count'];
                $check_total_price += $total_price;
                $orderNo = $this->createOrderSn();
                $orderProfit = $this->calculateOrderProfit($total_price, 'DEMAND_INCOME_SHARING', $user_room->is_role);
                $insertAll[] = [
                    'order_no'          => $orderNo,
                    'user_id'           => $demand->user_id_boss,
                    'anchor_id'         => $order['anchor_id'],
                    'ability_id'        => 0,
                    'service_time'      => $date_at,
                    'created_at'        => $date_at,
                    'updated_at'        => $date_at,
                    'count'             => $order['count'],
                    'price'             => $price,
                    'total_price'       => $total_price,
                    'remark'            => $order['remark'] ?: $demand->remark,
                    'game_name'         => $accompany_game['name'],
                    'game_id'           => $accompany_game['id'],
                    'coupon_id'         => 0,
                    'coupon_price'      => 0,
                    'status'            => 1,
                    'profit'            => $orderProfit['profit'],
                    'service_fee'       => $orderProfit['service_fee'],
                    'fanli_fee'         => $orderProfit['fanli_fee'],
                    'from_fanli_fee'    => $orderProfit['from_fanli_fee'],
                    'unit'              => $accompany_game['unit'],
                    'user_news'         => 0,
                    'anchor_news'       => 0,
                    'type'              => $accompany_game['type'],
                    'from_room_id'      => 0,
                    'room_demand_id'    => $params['demand_id'],
                    'room_id'           => $params['room_id'],
                ];
//            }
        }
        if ($check_total_price != $params['total_price']) {
            throw new BasicException(-1, "价格错误，前端：{$params['total_price']}，后端：{$check_total_price}");
        }

        DB::beginTransaction();
        try {
            $demand_update = [
                'total_price' => $check_total_price,
            ];
            $model_room_demand->where('id', $params['demand_id'])->update($demand_update);
            //陪玩单信息、收礼机收满后创建订单
            app('redis')->set('demand:accompany_order:'.$params['demand_id'], json_encode($insertAll));

            DB::commit();
        } catch (\BasicException $e){
            DB::rollBack();
            throw new BasicException(-1, $e->getMessage());
        }
        return true;
    }

    public function sendDemandGift($demandId)
    {
        $redisKeyComplete = AccompanyEnum::DEMAND_COMPLETE;
        if (!app('redis')->hexists($redisKeyComplete, $demandId)) {
            return true;
        }

        //发送消息，订单超时自动完成处理
        $orderAll = AccompanyOrder::query()->where('room_demand_id', $demandId)->get()->toArray();
        if (!empty($orderAll)) {
            foreach ($orderAll as $order) {
                //私聊消息
                $content = '对方已确认' . $order['game_name'] . '订单！';
                $userMessage = '请与大神商量服务时间（24小时不处理将会自动完成并结算）';
                $toUserMessage = '请向对方询问游戏具体区服及昵称进行服务';
                $this->shareUserMessage($content, $userMessage, $order['user_id'], $order['anchor_id'], 0);
                $content = '您已确认' . $order['game_name'] . '订单！';
                $this->shareUserMessage($content, $toUserMessage, $order['anchor_id'], $order['user_id'], 1);
                dispatch((new AccompanyFinishJob($order['id']))->delay(self::FINISH_TIME));
            }
            app('redis')->del('demand:accompany_order:'.$demandId);
            app('redis')->hdel($redisKeyComplete, $demandId);
            app('redis')->del('demand:total:'.$demandId);
        }
        return true;
    }

    public function cancelDemandOrder($params)
    {
        //status 0发布1结单2弃单3主播试音4选择主播5送礼确认
        $demand = app('model_room_demand')->where('id', $params['demand_id'])->first();
        if (empty($demand) || in_array($demand->status, [1, 2])) {
            throw new BasicException(-1, "订单状态错误");
        }
        try{
            $demand->status = 2;
            $demand->cancel_reason = $params['cancel_reason'];
            $demand->save();
            app('redis')->del('demand:accompany_order:'.$demand->id);
            AccompanyOrder::query()->where('room_demand_id', $demand->id)->update(['status' => -3]);

            $pushObj = new PushService(0, $demand->room_id);
            $pushObj->roomDemandUpdate([
                'status' => -1,
            ]);
        } catch (\BasicException $e) {
            throw new BasicException($e->getCode(), $e->getMessage());
        }

        return true;
    }

    public function setDemandOrderStatus($params)
    {
        if (!in_array($params['status'], [0, 3, 4, 5])) {
            throw new BasicException(-1, "状态错误");
        }
        $demand = app('model_room_demand')->where('id', $params['demand_id'])->first();
        if (empty($demand)) {
            throw new BasicException(-1, "订单错误");
        }
        try{
            if ($demand->status != $params['status']) {
                $demand->status = $params['status'];
                $demand->save();
                $pushObj = new PushService(0, $demand->room_id);
                $pushObj->roomDemandUpdate([
                    'status' => $params['status'],
                    'total_price' => $demand->total_price,
                ]);
                if ($params['status'] == 5) {
                    $pushObjBoss = new PushService($demand->user_id_boss, $demand->room_id);
                    $pushObjBoss->roomDemandToBoss([
                        'toast' => "请将{$demand->total_price}金币的礼物赠送给嘉宾右侧的收礼员哦",
                    ]);
                }
            }
        } catch (\BasicException $e) {
            throw new BasicException($e->getCode(), $e->getMessage());
        }

        return [
            'demand_id' => $demand->id,
            'game_id' => $demand->game_id,
            'price' => $demand->price,
            'total_price' => $demand->total_price,
            'remark' => $demand->remark,
            'status' => $demand->status,
        ];

    }

}
